from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.common.exceptions import StaleElementReferenceException, TimeoutException

def get_absolute_xpath(element):
    """递归地构造一个元素的绝对 XPath"""
    if element.tag_name.lower() == "html":
        return "/html"

    parent = element.find_element(By.XPATH, "..")
    siblings = parent.find_elements(By.XPATH, "*")
    index = siblings.index(element) + 1  # XPath 索引从1开始

    tag_name = element.tag_name
    return f"{get_absolute_xpath(parent)}/{tag_name}[{index}]"


def get_child_elements_with_retry(driver, by, value, retries=3):
    """尝试多次获取元素以避免 StaleElementReferenceException"""
    for attempt in range(retries):
        try:
            elements = driver.find_elements(by, value)
            return elements
        except StaleElementReferenceException:
            if attempt < retries - 1:
                continue
            else:
                raise
    return []


def get_child_elements(driver, parent_xpath):
    """获取指定父元素的所有直接子元素并构造它们的绝对 XPath"""
    try:
        # 等待直到父元素可见
        parent_element = WebDriverWait(driver, 10).until(
            EC.visibility_of_element_located((By.XPATH, parent_xpath))
        )

        # 获取所有直接子元素
        child_elements = get_child_elements_with_retry(driver, By.XPATH, parent_xpath + "/*")

        # 构造每个子元素的绝对 XPath
        xpaths = []
        for element in child_elements:
            try:
                absolute_xpath = get_absolute_xpath(element)
                xpaths.append(absolute_xpath)
            except StaleElementReferenceException:
                print("Element became stale before its XPath could be determined.")

        return xpaths
    except TimeoutException:
        print("Parent element not found or did not become visible within the timeout period.")
        return []